/*
 * =====================================================================================
 *       Filename:  xsync.c
 *    Description:  文件同步传输服务主程序
 *        Created:  2015-01-07 15:40
 *       Modified:  2017-11-05 10:05
 *         Author:  mien, m@luym.cn
 * =====================================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>

#include "net.h"
#include "http/http.h"
#include "pool.h"
#include "config.h"
#include "executer.h"
#include "global.h"

#define DEFAULT_CONFIG_FILE "conf/xsync.conf"

static void daemonize() {
    int fd;

    if (fork() != 0) exit(0);
    setsid();

    char* logfile = getServerConfig("logfile");

    if (!logfile) {
        logfile = "/dev/null";
    }

    if ((fd = open(logfile, O_CREAT | O_RDWR | O_APPEND, 0644)) != -1) {
        //dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > STDERR_FILENO) close(fd);
    }
}

static void sigShutdownHandler(int sig) {
    char *msg;

    switch (sig) {
    case SIGINT:
        msg = "Received SIGINT scheduling shutdown...\n";
        break;
    case SIGTERM:
        msg = "Received SIGTERM scheduling shutdown...\n";
        break;
    default:
        msg = "Received shutdown signal, scheduling shutdown...\n";
    }
    DEBUG((msg));
}

void setupSignalHandlers(void) {
    struct sigaction act;

    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = sigShutdownHandler;
    sigaction(SIGTERM, &act, NULL);
    sigaction(SIGINT, &act, NULL);
}

int main(int argc, char* argv[])
{
    loadConfig(argv[0], 
        argc == 2 ? argv[1] : DEFAULT_CONFIG_FILE);

    setUidGid();

    if (!strcmp(getServerConfig("daemonize"), "yes")) {
        daemonize();
    }

    initExecuter();

    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();

    poolInit();
    cmdInit();

    tcpListen(
        getServerConfig("host"),
        getServerConfig("port"),
        poolHandle);

    cmdFree();
    poolDestroy();
    freeConfig();

    waitExecuter();

    return EXIT_SUCCESS;
}
